home *** CD-ROM | disk | FTP | other *** search
/ Total Network Tools 2002 / NextStepPublishing-TotalNetworkTools2002-Win95.iso / Archive / Offline Browsing / HTTrack.exe / data1.cab / Sources / src / htsname.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-04-28  |  39.6 KB  |  1,189 lines

  1. /* ------------------------------------------------------------ */
  2. /*
  3. HTTrack Website Copier, Offline Browser for Windows and Unix
  4. Copyright (C) Xavier Roche and other contributors
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20.  
  21. Important notes:
  22.  
  23. - We hereby ask people using this source NOT to use it in purpose of grabbing
  24. emails addresses, or collecting any other private information on persons.
  25. This would disgrace our work, and spoil the many hours we spent on it.
  26.  
  27.  
  28. Please visit our Website: http://www.httrack.com
  29. */
  30.  
  31.  
  32. /* ------------------------------------------------------------ */
  33. /* File: httrack.c subroutines:                                 */
  34. /*       savename routine (compute output filename)             */
  35. /* Author: Xavier Roche                                         */
  36. /* ------------------------------------------------------------ */
  37.  
  38. #include "htsname.h"
  39.  
  40. /* specific definitions */
  41. #include "htsbase.h"
  42. #include "htstools.h"
  43. #include "htsmd5.h"
  44. #include <stdio.h>
  45. #include <stdlib.h>
  46. #include <ctype.h>
  47. /* END specific definitions */
  48.  
  49. #undef test_flush
  50. #define test_flush if (opt->flush) { fflush(opt->log); fflush(opt->errlog); }
  51.  
  52. #define ADD_STANDARD_PATH \
  53.     {  /* ajout nom */\
  54.       char buff[HTS_URLMAXSIZE*2];\
  55.       buff[0]='\0';\
  56.       strncat(buff,start_pos,(int) nom_pos - (int) start_pos);\
  57.       url_savename_addstr(save,buff);\
  58.     }
  59.  
  60. #define ADD_STANDARD_NAME(shortname) \
  61.     {  /* ajout nom */\
  62.       char buff[HTS_URLMAXSIZE*2];\
  63.       standard_name(buff,dot_pos,nom_pos,fil_complete,(shortname));\
  64.       url_savename_addstr(save,buff);\
  65.     }
  66.  
  67.  
  68. /* Avoid stupid DOS system folders/file such as 'nul' */
  69. /* Based on linux/fs/umsdos/mangle.c */
  70. static const char *hts_tbdev[] =
  71. {
  72.     "/prn", "/con", "/aux", "/nul",
  73.     "/lpt1", "/lpt2", "/lpt3", "/lpt4",
  74.     "/com1", "/com2", "/com3", "/com4",
  75.     "/clock$",
  76.     "/emmxxxx0", "/xmsxxxx0", "/setverxx",
  77.     ""
  78. };
  79.  
  80.  
  81.  
  82. // forme le nom du fichier α sauver (save) α partir de fil et adr
  83. // systΦme intelligent, qui renomme en cas de besoin (exemple: deux INDEX.HTML et index.html)
  84. int url_savename(char* adr_complete,char* fil_complete,char* save,char* former_adr,char* former_fil,char* referer_adr,char* referer_fil,httrackp* opt,lien_url** liens,int lien_tot,lien_back* back,int back_max,cache_back* cache,hash_struct* hash,int ptr,int numero_passe) {
  85.   char newfil[HTS_URLMAXSIZE*2];   /* ="" */
  86.   char* fil;
  87.   char* adr;
  88.   char* print_adr;
  89.   char *start_pos=NULL,*nom_pos=NULL,*dot_pos=NULL;  // Position nom et point
  90.   // pour changement d'extension ou de nom (content-disposition)
  91.   int ext_chg=0;
  92.   char ext[256];
  93.   //CLEAR
  94.   newfil[0]=ext[0]='\0';
  95.  
  96.   // effacer save
  97.   save[0]='\0';
  98.   // fil
  99.   fil = fil_complete;
  100.   // et adr (sauter user/pass)
  101.   // on prend le parti de mettre les fichiers avec login/pass au mΩme endroit que si ils
  102.   // Θtaient capturΘs sans ces paramΦtres
  103.   // c'est pour cette raison qu'on ignore totalement adr_complete (mΩme pour la recherche en table de hachage)
  104.   adr=jump_identification(adr_complete);
  105.  
  106.   // α afficher sans ftp://
  107.   print_adr=jump_protocol(adr);
  108.  
  109.   // court-circuit pour lien primaire
  110.   if (strnotempty(adr)==0) {
  111.     if (strcmp(fil,"primary")==0) {
  112.       strcat(save,"primary.html");
  113.       return 0;
  114.     }
  115.   }
  116.  
  117.  
  118.   // vΘrifier que le nom n'a pas dΘja ΘtΘ calculΘ (si oui le renvoyer tel que)
  119.   // vΘrifier que le nom n'est pas dΘja pris...
  120.   // NOTE: si on cherche /toto/ et que /toto est trouvΘ on le prend (et rΘciproquqment) ** // **
  121.   if (liens!=NULL) { 
  122.     register int i;
  123.  
  124. #if HTS_HASH
  125.     i=hash_read(hash,adr,fil_complete,1);      // recherche table 1 (adr+fil)
  126.     if (i>=0) {    // ok, trouvΘ
  127.       strcpy(save,liens[i]->sav);
  128.       return 0;
  129.     }
  130.     i=hash_read(hash,adr,fil_complete,2);      // recherche table 2 (former_adr+former_fil)
  131.     if (i>=0) {    // ok, trouvΘ
  132.       // copier location moved!
  133.       strcpy(adr_complete,liens[i]->adr);
  134.       strcpy(fil_complete,liens[i]->fil);
  135.       // et save
  136.       strcpy(save,liens[i]->sav);  // copier (formΘ α partir du nouveau lien!)
  137.       return 0;
  138.     }
  139. #else
  140.     for(i=lien_tot-1;i>=0;i--) {        
  141. #if HTS_CASSE
  142.       if ((strcmp(liens[i]->adr,adr)==0) && (strcmp(liens[i]->fil,fil_complete)==0))
  143. #else
  144.       if ((strfield2(liens[i]->adr,adr)) && (strfield2(liens[i]->fil,fil_complete)))
  145. #endif
  146.       {    // ok c'est le mΩme lien, adresse dΘja dΘfinie
  147.         strcpy(save,liens[i]->sav);
  148.         return 0;
  149.       }
  150.       if (liens[i]->former_adr) {     // tester ancienne loc?
  151. #if HTS_CASSE
  152.         if ((strcmp(liens[i]->former_adr,adr)==0) && (strcmp(liens[i]->former_fil,fil_complete)==0))
  153. #else
  154.         if ((strfield2(liens[i]->former_adr,adr)) && (strfield2(liens[i]->former_fil,fil_complete)))
  155. #endif
  156.         {
  157.           // copier location moved!
  158.           strcpy(adr_complete,liens[i]->adr);
  159.           strcpy(fil_complete,liens[i]->fil);
  160.           // et save
  161.           strcpy(save,liens[i]->sav);  // copier (formΘ α partir du nouveau lien!)
  162.           return 0;
  163.         }
  164.       }
  165.     }
  166. #endif
  167.  
  168.     // chercher sans / ou avec / dans former
  169.     {
  170.       char fil_complete_patche[HTS_URLMAXSIZE*2];
  171.       strcpy(fil_complete_patche,fil_complete);
  172.       // Version avec ou sans /
  173.       if (fil_complete_patche[strlen(fil_complete_patche)-1]=='/')
  174.         fil_complete_patche[strlen(fil_complete_patche)-1]='\0';
  175.       else
  176.         strcat(fil_complete_patche,"/");
  177. #if HTS_HASH
  178.       i=hash_read(hash,adr,fil_complete_patche,2);      // recherche table 2 (former_adr+former_fil)
  179.       if (i>=0) {
  180.         // Θcraser fil et adr (pas former_fil?????)
  181.         strcpy(adr_complete,liens[i]->adr);
  182.         strcpy(fil_complete,liens[i]->fil);
  183.         // Θcrire save
  184.         strcpy(save,liens[i]->sav);
  185.         return 0;
  186.       }
  187. #else
  188.       // mΩme boucle en gros
  189.       for(i=lien_tot-1;i>=0;i--) {        
  190.         if (liens[i]->former_adr) {    // former-adr?
  191. #if HTS_CASSE
  192.           if ((strcmp(liens[i]->former_adr,adr)==0) && (strcmp(liens[i]->former_fil,fil_complete_patche)==0))
  193. #else
  194.           if ((strfield2(liens[i]->former_adr,adr)) && (strfield2(liens[i]->former_fil,fil_complete_patche)))
  195. #endif
  196.           {    // ok c'est le mΩme lien, adresse dΘja dΘfinie
  197.             // Θcraser fil et adr (pas former_fil?????)
  198.             strcpy(adr_complete,liens[i]->adr);
  199.             strcpy(fil_complete,liens[i]->fil);
  200.             // Θcrire save
  201.             strcpy(save,liens[i]->sav);
  202.             return 0;
  203.           }
  204.         }
  205.       }
  206. #endif
  207.     }
  208.   }
  209.  
  210.   // vΘrifier la non prΘsence de paramΦtres dans le nom de fichier
  211.   // si il y en a, les supprimer (ex: truc.cgi?subj=aspirateur)
  212.   // nΘanmoins, gardΘ pour vΘrifier la non duplication (voir aprΦs)
  213.   {
  214.     char* a;
  215.     a=strchr(fil,'?');
  216.     if (a!=NULL) {
  217.       strncat(newfil,fil,(int) a-(int) fil);
  218.     } else {
  219.       strcpy(newfil,fil);
  220.     }
  221.     fil=newfil;
  222.   }
  223.   // dΘcoder %
  224.   strcpy(fil,unescape_http(fil));
  225.   /*
  226.   {
  227.     char tempo[HTS_URLMAXSIZE*2];
  228.     int i,j=0;
  229.     for (i=0;i<(int) strlen(fil);i++) {
  230.       if (fil[i]=='%') {
  231.         i++;
  232.         tempo[j++]=(char) ehex(fil+i);
  233.         i++;    // sauter 2 caractΦres finalement
  234.       } else
  235.         tempo[j++]=fil[i];
  236.     }
  237.     tempo[j++]='\0';
  238.     strcpy(fil,tempo);
  239.   }
  240.   */
  241.  
  242.  
  243.   /* replace shtml to html.. */
  244.   if (ishtml(fil)==1) {       /* .html,.shtml,.. */
  245.     if ( 
  246.       (strcmp(get_ext(fil),"html") != 0)
  247.       && (strcmp(get_ext(fil),"htm") != 0)
  248.       ) {
  249.         strcpy(ext,"html");
  250.         ext_chg=1;
  251.     }
  252.   }
  253.  
  254.  
  255.   // si option check_type activΘe
  256.   if ((opt->check_type) && (!ext_chg)) {
  257.     if ( (strncmp(adr_complete,"file://",7)) && (strncmp(adr_complete,"ftp://",6)) ) {
  258.       // tester type avec requΦte HEAD si on ne connait pas le type du fichier
  259.       if (!(   (opt->check_type==1) && (fil[strlen(fil)-1]=='/')   ))    // slash doit Ωtre html?
  260.       if (ishtml(fil)<0) { // on ne sait pas si c'est un html ou un fichier..
  261.         // lire dans le cache
  262.         htsblk r = cache_read(opt,cache,adr,fil,NULL);              // test uniquement
  263.         if (r.statuscode != -1) {  // pas d'erreur de lecture cache
  264.           char s[16]; s[0]='\0';
  265.           if ( (opt->debug>1) && (opt->log!=NULL) ) {
  266.             fspc(opt->log,"debug"); fprintf(opt->log,"Testing link type (from cache) %s%s"LF,adr_complete,fil_complete);
  267.             test_flush;
  268.           }
  269.           if (strnotempty(r.cdispo)) {        /* filename given */
  270.             ext_chg=2;      /* change filename */
  271.             strcpy(ext,r.cdispo);
  272.           }
  273.           else if (!may_unknown(r.contenttype)) {  // on peut patcher α priori?
  274.             give_mimext(s,r.contenttype);  // obtenir extension
  275.             if (strnotempty(s)>0) {        // on a reconnu l'extension
  276.               ext_chg=1;
  277.               strcpy(ext,s);
  278.             }
  279.           }
  280.           //
  281.         } else {          // test imposible dans le cache, faire une requΩte
  282.           //
  283. #if HTS_ANALYSTE==2
  284.           int hihp=_hts_in_html_parsing;
  285. #endif
  286.           int has_been_moved=0;
  287.           char curr_adr[HTS_URLMAXSIZE*2],curr_fil[HTS_URLMAXSIZE*2];
  288.           curr_adr[0]=curr_fil[0]='\0';
  289. #if HTS_ANALYSTE==2
  290.           _hts_in_html_parsing=2;  // test
  291. #endif
  292.           if ( (opt->debug>1) && (opt->log!=NULL) ) {
  293.             fspc(opt->log,"debug"); fprintf(opt->log,"Testing link type %s%s"LF,adr_complete,fil_complete);
  294.             test_flush;
  295.           }
  296.           strcpy(curr_adr,adr_complete);
  297.           strcpy(curr_fil,fil_complete);
  298.           // ajouter dans le backing le fichier en mode test
  299.           // savename: rien car en mode test
  300.           if (back_add(back,back_max,opt,cache,curr_adr,curr_fil,BACK_ADD_TEST,referer_adr,referer_fil,1,NULL)!=-1) {
  301.             int b;
  302.             b=back_index(back,back_max,curr_adr,curr_fil,BACK_ADD_TEST);         
  303.             if (b>=0) {
  304.               int petits_tours=0;
  305.               int get_test_request=0;       // en cas de bouclage sur soi mΩme avec HEAD, tester avec GET.. parfois c'est la cause des problΦmes
  306.               do {
  307.                 // temps α attendre, et remplir autant que l'on peut le cache (backing)
  308.                 if (back[b].status>0) back_wait(back,back_max,opt,cache,0);        
  309.                 if (ptr>=0)
  310.                   back_fillmax(back,back_max,opt,cache,liens,ptr,numero_passe,lien_tot);
  311.   
  312.                 // on est obligΘ d'appeler le shell pour le refresh..
  313. #if HTS_ANALYSTE==2
  314.                 {
  315.                   LLint nb=back_transfered(HTS_STAT.stat_bytes,back,back_max);
  316.                   int nbk=backlinks_done(liens,lien_tot,ptr);
  317.                   engine_stats();
  318.                   //if (!hts_htmlcheck_loop(back,back_max,b,-1,lien_tot,-1,-1,-1,back_nsoc(back,back_max) )) {
  319.                   if (!hts_htmlcheck_loop(back,back_max,b,ptr,lien_tot,nb,-1,-1,back_nsoc(back,back_max),-1,-1,-1,(int)HTS_STAT.rate,nbk )) {
  320.                     return -1;
  321.                   } else if (_hts_cancel) {    // cancel 2 ou 1 (cancel parsing)
  322.                     back_delete(back,b);       // cancel test
  323.                   }
  324.                 }
  325. #endif
  326.                 
  327.                 
  328.                 // traitement des 304,303..
  329.                 if (back[b].status<=0) {
  330.                   if (    (back[b].r.statuscode==301)
  331.                        || (back[b].r.statuscode==302)
  332.                        || (back[b].r.statuscode==303)
  333.                        || (back[b].r.statuscode==307)
  334.                      ) {    // agh moved.. un tit tour de plus
  335.                     if ((petits_tours<5) && (former_adr) && (former_fil)) { // on va pas tourner en rond non plus!
  336.                       if ((int) strnotempty(back[b].r.location)) {    // location existe!
  337.                         char mov_url[HTS_URLMAXSIZE*2],mov_adr[HTS_URLMAXSIZE*2],mov_fil[HTS_URLMAXSIZE*2];
  338.                         mov_url[0]=mov_adr[0]=mov_fil[0]='\0';
  339.                         //
  340.                         strcpy(mov_url,back[b].r.location);    // copier URL
  341.                         if (ident_url_relatif(mov_url,curr_adr,curr_fil,mov_adr,mov_fil)>=0) {                        
  342.                           // si non bouclage sur soi mΩme, ou si test avec GET non testΘ
  343.                           if ((strcmp(mov_adr,curr_adr)) || (strcmp(mov_fil,curr_fil)) || (get_test_request==0)) {
  344.                             // bouclage?
  345.                             if ((!strcmp(mov_adr,curr_adr)) && (!strcmp(mov_fil,curr_fil)))
  346.                               get_test_request=1;     // faire requΦte avec GET
  347.  
  348.                             // recopier former_adr/fil?
  349.                             if ((former_adr) && (former_fil)) {
  350.                               if (strnotempty(former_adr)==0) {    // Pas dΘja notΘ
  351.                                 strcpy(former_adr,curr_adr);
  352.                                 strcpy(former_fil,curr_fil);
  353.                               }
  354.                             }
  355.  
  356.                             // ftp: stop!
  357.                             if (!strncmp(mov_url,"ftp://",6)) {    // ftp, ok on arrΩte
  358.                               has_been_moved = 1;
  359.                               back_delete(back,b);    // ok
  360.                               strcpy(curr_adr,mov_adr);
  361.                               strcpy(curr_fil,mov_fil);
  362.                             } else {
  363.                               char* methode;
  364.                               if (!get_test_request)
  365.                                 methode=BACK_ADD_TEST;      // tester avec HEAD
  366.                               else {
  367.                                 methode=BACK_ADD_TEST2;     // tester avec GET
  368.                                 if ( opt->errlog!=NULL ) {
  369.                                   fspc(opt->errlog,"warning"); fprintf(opt->errlog,"Loop with HEAD request (during prefetch) at %s%s"LF,curr_adr,curr_fil);
  370.                                   test_flush;
  371.                                 }                    
  372.                               }
  373.                               // Ajouter
  374.                               if (back_add(back,back_max,opt,cache,mov_adr,mov_fil,methode,referer_adr,referer_fil,1,NULL)!=-1) {    // OK
  375.                                 if ( (opt->debug>1) && (opt->errlog!=NULL) ) {
  376.                                   fspc(opt->errlog,"warning"); fprintf(opt->errlog,"(during prefetch) %s (%d) to link %s at %s%s"LF,back[b].r.msg,back[b].r.statuscode,back[b].r.location,curr_adr,curr_fil);
  377.                                   test_flush;
  378.                                 }                    
  379.                                 
  380.                                 // libΘrer emplacement backing actuel et attendre le prochain
  381.                                 back_delete(back,b);
  382.                                 strcpy(curr_adr,mov_adr);
  383.                                 strcpy(curr_fil,mov_fil);
  384.                                 b=back_index(back,back_max,curr_adr,curr_fil,methode);         
  385.                                 if (!get_test_request)
  386.                                   has_been_moved = 1;       // sinon ne pas forcer has_been_moved car non dΘplacΘ
  387.                                 petits_tours++;
  388.                                 //
  389.                               } else {// sinon on fait rien et on s'en va.. (ftp etc)
  390.                                 if ( (opt->debug>1)  && (opt->errlog)) {
  391.                                   fspc(opt->errlog,"debug"); fprintf(opt->errlog,"Warning: Savename redirect backing error at %s%s"LF,mov_adr,mov_fil);
  392.                                   test_flush;
  393.                                 } 
  394.                               }
  395.                             }
  396.                           } else {
  397.                             if ( opt->errlog!=NULL ) {
  398.                               fspc(opt->errlog,"warning"); fprintf(opt->errlog,"Unable to test %s%s (loop to same filename)"LF,adr_complete,fil_complete);
  399.                               test_flush;
  400.                             }
  401.                           }
  402.                           
  403.                         }
  404.                       }
  405.                     } else{  // arrΩter les frais
  406.                       if ( opt->errlog!=NULL ) {
  407.                         fspc(opt->errlog,"warning"); fprintf(opt->errlog,"Unable to test %s%s (loop)"LF,adr_complete,fil_complete);
  408.                         test_flush;
  409.                       }
  410.                     }
  411.                   }  // ok, leaving
  412.                 }
  413.                 
  414.               } while(back[b].status>0);
  415.               
  416.               // Si non dΘplacΘ, forcer type?
  417.               if (!has_been_moved) {
  418.                 if (back[b].r.statuscode!=-10) {    // erreur
  419.                   if (strnotempty(back[b].r.contenttype)==0)
  420.                     strcpy(back[b].r.contenttype,"text/html");    // message d'erreur en html
  421.                   // Finalement on, renvoie un erreur, pour ne toucher α rien dans le code
  422.                   // libΘrer emplacement backing
  423.                   /*if (opt->errlog!=NULL) {
  424.                     fspc(opt->errlog,0); fprintf(opt->errlog,"Error: (during prefetch) %s (%d) to link %s at %s%s"LF,back[b].r.msg,back[b].r.statuscode,back[b].r.location,curr_adr,curr_fil);
  425.                     test_flush;
  426.                   }                    
  427.                   back_delete(back,b);
  428.                   return -1;        // ERREUR (404 par exemple)
  429.                   */
  430.                 } 
  431.                 
  432.                 {            // pas d'erreur, changer type?
  433.                   char s[16]="";
  434.                   if (strnotempty(back[b].r.cdispo)) {        /* filename given */
  435.                     ext_chg=2;      /* change filename */
  436.                     strcpy(ext,back[b].r.cdispo);
  437.                   }
  438.                   else if ((!may_unknown(back[b].r.contenttype)) || (!get_ext(back[b].url_fil)) ) {  // on peut patcher α priori? (pas interdit ou pas de type)
  439.                     give_mimext(s,back[b].r.contenttype);  // obtenir extension
  440.                     if (strnotempty(s)>0) {    // on a reconnu l'extension
  441.                       ext_chg=1;
  442.                       strcpy(ext,s);
  443.                     }
  444.                   }
  445.                 }
  446.               }
  447.               // FIN Si non dΘplacΘ, forcer type?
  448.  
  449.               // libΘrer emplacement backing
  450.               back_delete(back,b);
  451.               
  452.               // --- --- ---
  453.               // oops, a ΘtΘ dΘplacΘ.. on recalcule en rΘcursif (osons!)
  454.               if (has_been_moved) {
  455.                 // copier adr, fil (optionnel, mais sinon marche pas pour le rip)
  456.                 strcpy(adr_complete,curr_adr);
  457.                 strcpy(fil_complete,curr_fil);
  458.                 // copier adr, fil
  459.                 
  460.                 return url_savename(curr_adr,curr_fil,save,NULL,NULL,referer_adr,referer_fil,opt,liens,lien_tot,back,back_max,cache,hash,ptr,numero_passe);
  461.               }
  462.               // --- --- ---
  463.               
  464.             }
  465.             
  466.           } else {
  467.             printf("PANIC! : Savename Crash adding error, unexpected error found.. [%d]\n",__LINE__);
  468. #if BDEBUG==1
  469.             printf("error while savename crash adding\n");
  470. #endif
  471.             if (opt->errlog) {
  472.               fspc(opt->errlog,"error"); fprintf(opt->errlog,"Unexpected savename backing error at %s%s"LF,adr,fil_complete);
  473.               test_flush;
  474.             } 
  475.             
  476.           }
  477.           // restaurer
  478. #if HTS_ANALYSTE==2
  479.           _hts_in_html_parsing=hihp;
  480. #endif
  481.         }  // cachΘ?
  482.       }
  483.     }
  484.   }
  485.  
  486.  
  487.  
  488.   // - - - DEBUT NOMMAGE - - -
  489.  
  490.   // Donner nom par dΘfaut?
  491.   if (fil[strlen(fil)-1]=='/')  {
  492.     if (strncmp(adr_complete,"ftp://",6))
  493.       strcat(fil,DEFAULT_HTML);     // nommer page par dΘfaut!!
  494.     else {
  495.       if (!opt->proxy.active)
  496.         strcat(fil,DEFAULT_FTP);     // nommer page par dΘfaut (texte)
  497.       else
  498.         strcat(fil,DEFAULT_HTML);     // nommer page par dΘfaut (α priori ici html depuis un proxy http)
  499.     }
  500.   }
  501.   // Changer extension?
  502.   // par exemple, php3 sera sauvΘ en html, cgi en html ou gif, xbm etc.. selon les cas
  503.   if (ext_chg) {  // changer ext
  504.     char* a=fil+strlen(fil)-1;
  505.     if ( (opt->debug>1) && (opt->log!=NULL) ) {
  506.       fspc(opt->log,"debug");
  507.       if (ext_chg==1)
  508.         fprintf(opt->log,"Changing link extension %s%s to .%s"LF,adr_complete,fil_complete,ext);
  509.       else
  510.         fprintf(opt->log,"Changing link name %s%s to %s"LF,adr_complete,fil_complete,ext);
  511.       test_flush;
  512.     }
  513.     if (ext_chg==1) {
  514.       while(((int) a>(int) fil) && (*a!='.') && (*a!='/')) a--;
  515.       if (*a=='.') *a='\0';  // couper
  516.       strcat(fil,".");      // recopier point
  517.     } else {
  518.       while(((int) a>(int) fil) && (*a!='/')) a--;
  519.       if (*a=='/') a++;
  520.       *a='\0';
  521.    }
  522.     strcat(fil,ext);    // copier ext/nom
  523.   }
  524.  
  525.   // Rechercher premier / et dernier .
  526.   {  
  527.     char* a=fil+strlen(fil)-1;
  528.  
  529.     // passer structures
  530.     start_pos=fil;
  531.     while(((int) a>(int) fil) && (*a != '/') && (*a != '\\')) {
  532.       if (*a == '.')    // point? noter position
  533.         if (!dot_pos)
  534.           dot_pos=a;
  535.         a--;
  536.     }
  537.     if ((*a=='/') || (*a=='\\')) a++;
  538.     nom_pos = a;
  539.   }
  540.  
  541.   
  542.   // un nom de fichier est gΘnΘrΘ
  543.   // s'il existe dΘja, alors on le mofifie lΘgΦrement
  544.  
  545.   // ajouter nom du site Θventuellement en premier
  546.   if (opt->savename_type == -1) {    // utiliser savename_userdef! (%h%p/%n%q.%t)
  547.     char* a = opt->savename_userdef;
  548.     char* b = save;
  549.     /*char *nom_pos=NULL,*dot_pos=NULL;  // Position nom et point */
  550.     char tok;
  551.  
  552.     /*
  553.     {  // Rechercher premier /
  554.       char* a=fil+strlen(fil)-1;
  555.       // passer structures
  556.       while(((int) a>(int) fil) && (*a != '/') && (*a != '\\')) {
  557.         if (*a == '.')    // point? noter position
  558.         if (!dot_pos)
  559.           dot_pos=a;
  560.         a--;
  561.       }
  562.       if ((*a=='/') || (*a=='\\')) a++;
  563.       nom_pos = a;
  564.     }
  565.     */
  566.  
  567.     // Construire nom
  568.     while ((*a) && (((int) b - (int) save) < 800 ) ) {    // parser, et pas trop long..
  569.       if (*a == '%') {
  570.         int short_ver=0;
  571.         a++;
  572.         if (*a == 's') {
  573.           short_ver=1;
  574.           a++;
  575.         }
  576.         *b='\0';
  577.         switch(tok=*a++) {
  578.           case '[':            // %[param]
  579.             if (strchr(a,']')) {
  580.               char name[256];
  581.               char* c=name;
  582.               while(*a!=']') {
  583.                 *c++=*a++;
  584.               }
  585.               a++;
  586.               *c++='\0';
  587.               strcat(name,"=");           /* param=.. */
  588.               c=strchr(fil_complete,'?');
  589.               /* parameters exists */
  590.               if (c) {
  591.                 c=strstr(c,name);     /* finds param= */
  592.                 if (c) {
  593.                   c+=strlen(name);    /* jumps "param=" */
  594.                   while( (*c) && (*c!='&'))
  595.                     *b++=*c++;
  596.                 }
  597.               }
  598.             }
  599.           break;
  600.           case '%': *b++='%'; break;
  601.           case 'n':    // nom sans ext
  602.             if (dot_pos) {
  603.               if (!short_ver)    // Noms longs
  604.                 strncat(b,nom_pos,(int) dot_pos - (int) nom_pos);
  605.               else
  606.                 strncat(b,nom_pos,min((int) dot_pos - (int) nom_pos,8));
  607.             } else {
  608.               if (!short_ver)    // Noms longs
  609.                 strcpy(b,nom_pos);
  610.               else
  611.                 strncat(b,nom_pos,8);
  612.             }
  613.             b+=strlen(b);   // pointer α la fin
  614.             break;
  615.           case 'N':    // nom avec ext
  616.             // RECOPIE NOM + EXT
  617.             *b='\0';
  618.             if (dot_pos) {
  619.               if (!short_ver)    // Noms longs
  620.                 strncat(b,nom_pos,(int) dot_pos - (int) nom_pos);
  621.               else
  622.                 strncat(b,nom_pos,min((int) dot_pos - (int) nom_pos,8));
  623.             } else {
  624.               if (!short_ver)    // Noms longs
  625.                 strcpy(b,nom_pos);
  626.               else
  627.                 strncat(b,nom_pos,8);
  628.             }
  629.             b+=strlen(b);   // pointer α la fin
  630.             // RECOPIE NOM + EXT
  631.             *b='\0';
  632.             if (dot_pos) {
  633.               if (!short_ver)    // Noms longs
  634.                 strcpy(b,dot_pos+1);
  635.               else
  636.                 strncat(b,dot_pos+1,3);
  637.             } else {
  638.               if (!short_ver)    // Noms longs
  639.                 strcpy(b,DEFAULT_EXT);    // pas de..
  640.               else
  641.                 strcpy(b,DEFAULT_EXT_SHORT);    // pas de..
  642.             }
  643.             b+=strlen(b);   // pointer α la fin
  644.             //
  645.             break;
  646.           case 't':    // ext
  647.             *b='\0';
  648.             if (dot_pos) {
  649.               if (!short_ver)    // Noms longs
  650.                 strcpy(b,dot_pos+1);
  651.               else
  652.                 strncat(b,dot_pos+1,3);
  653.             } else {
  654.               if (!short_ver)    // Noms longs
  655.                 strcpy(b,DEFAULT_EXT);    // pas de..
  656.               else
  657.                 strcpy(b,DEFAULT_EXT_SHORT);    // pas de..
  658.             }
  659.             b+=strlen(b);   // pointer α la fin
  660.             break;
  661.           case 'p':    // path sans dernier /
  662.             *b='\0';
  663.             if (nom_pos != fil + 1) { // pas: /index.html (chemin nul)
  664.               if (!short_ver) {   // Noms longs
  665.                 strncat(b,fil,(int) nom_pos - (int) fil - 1);
  666.               } else {
  667.                 char pth[HTS_URLMAXSIZE*2],n83[HTS_URLMAXSIZE*2];
  668.                 pth[0]=n83[0]='\0';
  669.                 //
  670.                 strncat(pth,fil,(int) nom_pos - (int) fil - 1);
  671.                 long_to_83(n83,pth);
  672.                 strcpy(b,n83);
  673.               }
  674.             }
  675.             b+=strlen(b);   // pointer α la fin
  676.             break;
  677.           case 'h':    // host
  678.             *b='\0';
  679.             if (strcmp(adr_complete,"file://")==0) {
  680.               if (!short_ver)    // Noms longs
  681.                 strcpy(b,"localhost");
  682.               else
  683.                 strcpy(b,"local");
  684.             } else {
  685.               if (!short_ver)    // Noms longs
  686.                 strcpy(b,print_adr);
  687.               else
  688.                 strncat(b,print_adr,8);
  689.             }
  690.             b+=strlen(b);   // pointer α la fin
  691.             break;
  692.           case 'M':         /* host/address?query MD5 (128-bits) */
  693.             *b='\0';
  694.             {
  695.               char digest[32+2];
  696.               char buff[HTS_URLMAXSIZE*2];
  697.               digest[0]=buff[0]='\0';
  698.               strcpy(buff,adr);
  699.               strcat(buff,fil_complete);
  700.               domd5mem(buff,strlen(buff),digest,1,0);
  701.               strcpy(b,digest);
  702.             }
  703.             b+=strlen(b);   // pointer α la fin
  704.             break;
  705.           case 'Q': case 'q':         /* query MD5 (128-bits/16-bits) 
  706.                                          GENERATED ONLY IF query string exists! */
  707.             *b='\0';
  708.             strncat(b,url_md5(fil_complete),(tok == 'Q')?32:4);
  709.             b+=strlen(b);   // pointer α la fin
  710.             break;
  711.         }
  712.       } else
  713.         *b++=*a++;
  714.     }
  715.     *b++='\0';
  716.     //
  717.     // Types prΘdΘfinis
  718.     //
  719.  
  720.   } 
  721.   //
  722.   // Structure originale
  723.   else if (opt->savename_type%100==0) { 
  724.     /* recopier www.. */
  725.     if (opt->savename_type!=100) {  
  726.       if (((opt->savename_type/1000)%2)==0) {    // >1000 signifie "pas de www/"
  727.         if (strcmp(adr_complete,"file://")==0) {
  728.           //## if (*adr==lOCAL_CHAR) {
  729.           if (!opt->savename_83)  // noms longs
  730.             strcat(save,"localhost");
  731.           else
  732.             strcat(save,"local");
  733.         } else {
  734.           // adresse url
  735.           if (!opt->savename_83) {  // noms longs
  736.             strcat(save,print_adr);
  737.           } else {  // noms 8-3
  738.             if (strlen(print_adr)>4) {
  739.               if (strfield(print_adr,"www."))
  740.                 strncat(save,print_adr+4,8);
  741.               else
  742.                 strncat(save,print_adr,8);
  743.             } else strncat(save,print_adr,8);
  744.           }
  745.         }
  746.         if (*fil!='/') strcat(save,"/");
  747.       }
  748.     }
  749.   
  750. #if HTS_CASSE==0
  751.     hts_lowcase(save);
  752. #endif  
  753.         
  754.     /*
  755.     // ne sert α rien car a dΘja ΘtΘ filtrΘ normalement
  756.     if ((*fil=='.') && (*(fil+1)=='/'))          // ./index.html ** //
  757.       url_savename_addstr(save,fil+2);
  758.     else                                               // index.html ou /index.html
  759.       url_savename_addstr(save,fil);
  760.     if (save[strlen(save)-1]=='/') 
  761.       strcat(save,DEFAULT_HTML);     // nommer page par dΘfaut!!
  762. */
  763.  
  764.     /* add name */
  765.     ADD_STANDARD_PATH;
  766.     ADD_STANDARD_NAME(0);
  767.  
  768.   }
  769.   //
  770.   // Structure html/image
  771.   else {    
  772.     // dossier "web" ou "www.xxx" ?
  773.     if (((opt->savename_type/1000)%2)==0) {    // >1000 signifie "pas de www/"
  774.       if ((opt->savename_type/100)%2) {
  775.         if (strcmp(adr_complete,"file://")==0) {
  776.         //## if (*adr==lOCAL_CHAR) {
  777.           if (!opt->savename_83)  // noms longs
  778.             strcat(save,"localhost/");
  779.           else
  780.             strcat(save,"local/");
  781.         } else {
  782.           // adresse url
  783.           if (!opt->savename_83) {  // noms longs
  784.             strcat(save,print_adr); strcat(save,"/");
  785.           } else {  // noms 8-3
  786.             if (strlen(print_adr)>4) {
  787.               if (strfield(print_adr,"www."))
  788.                 strncat(save,print_adr+4,8);
  789.               else
  790.                 strncat(save,print_adr,8);
  791.               strcat(save,"/");
  792.             } else { 
  793.               strncat(save,print_adr,8); strcat(save,"/");
  794.             }
  795.           }
  796.         }
  797.       } else {
  798.         strcat(save,"web/");    // rΘpertoire gΘnΘral
  799.       }
  800.     } 
  801.  
  802.     // si un html α coup s√r
  803.     if ( (ext_chg!=0) ? (ishtml_ext(ext)==1) : (ishtml(fil)==1) ) {
  804.       if (opt->savename_type%100==2) {  // html/
  805.         strcat(save,"html/");
  806.       }
  807.     } else {
  808.       if ((opt->savename_type%100==1) || (opt->savename_type%100==2)) {  // html & images
  809.         strcat(save,"images/");
  810.       }
  811.     }
  812.     
  813.     switch (opt->savename_type%100) {
  814.     case 4: case 5: {           // sΘparer par types
  815.       char* a=fil+strlen(fil)-1;
  816.       // passer structures
  817.       while(((int) a>(int) fil) && (*a != '/') && (*a != '\\')) a--;      
  818.       if ((*a=='/') || (*a=='\\')) a++;
  819.  
  820.       // html?
  821.       if ( (ext_chg!=0) ? (ishtml_ext(ext)==1) : (ishtml(fil)==1) ) {
  822.         if (opt->savename_type%100==5)
  823.           strcat(save,"html/");
  824.       } else {
  825.         char* a=fil+strlen(fil)-1;
  826.         while(((int) a>(int) fil) && (*a != '/') && (*a != '.')) a--;      
  827.         if (*a!='.')
  828.           strcat(save,"other");
  829.         else
  830.           strcat(save,a+1);
  831.         strcat(save,"/");
  832.       }
  833.       /*strcat(save,a);*/
  834.       /* add name */
  835.       ADD_STANDARD_NAME(0);
  836.             }
  837.       break;
  838.     case 99: {                  // 'codΘ' .. c'est un gadget
  839.       int i;
  840.       int j;
  841.       char* a;
  842.       char C[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-";
  843.       int L;
  844.       // pseudo-CRC sur fil et adr pour initialiser gΘnΘrateur alΘatoire..
  845.       unsigned int s=0;
  846.       L=strlen(C);
  847.       for(i=0;i<(int) strlen(fil_complete);i++) {
  848.         s+=(unsigned int) fil_complete[i];
  849.       }
  850.       for(i=0;i<(int) strlen(adr_complete);i++) {
  851.         s+=(unsigned int) adr_complete[i];
  852.       }
  853.       srand(s);
  854.       
  855.       j=strlen(save);
  856.       for(i=0;i<8;i++) {
  857.         char c=C[(rand()%L)];
  858.         save[i+j]=c;
  859.       }
  860.       save[i+j]='\0';
  861.       // ajouter extension
  862.       a=fil+strlen(fil)-1;
  863.       while(((int) a>(int) fil) && (*a != '/') && (*a != '.')) a--;
  864.       if (*a=='.') {
  865.         strcat(save,a);    // ajouter
  866.       }
  867.              } 
  868.       break;
  869.     default: {   // noms sans les noms des rΘpertoires
  870.       // ne garder que le nom, pas la structure
  871.       /*
  872.       char* a=fil+strlen(fil)-1;
  873.       while(((int) a>(int) fil) && (*a != '/') && (*a != '\\')) a--;      
  874.       if ((*a=='/') || (*a=='\\')) a++;
  875.       strcat(save,a);
  876.       */
  877.  
  878.       /* add name */
  879.       ADD_STANDARD_NAME(0);
  880.             }
  881.       break;
  882.     }
  883.  
  884. #if HTS_CASSE==0
  885.     hts_lowcase(save);
  886. #endif  
  887.  
  888.     if (save[strlen(save)-1]=='/') 
  889.       strcat(save,DEFAULT_HTML);     // nommer page par dΘfaut!!
  890.   }
  891.  
  892.  
  893.   // vΘrifier qu'on ne doit pas forcer l'extension
  894.   // par exemple, asp sera sauvΘ en html, cgi en html ou gif, xbm etc.. selon les cas
  895.   /*if (ext_chg) {
  896.     char* a=save+strlen(save)-1;
  897.     while(((int) a>(int) save) && (*a!='.') && (*a!='/')) a--;
  898.     if (*a=='.') *a='\0';  // couper
  899.     // recopier extension
  900.     strcat(save,".");
  901.     strcat(save,ext);    // copier ext
  902.   }*/
  903.   // de mΩme en cas de manque d'extension on en place une de maniΦre forcΘe..
  904.   // cela Θvite les /chez/toto et les /chez/toto/index.html incompatibles
  905.   if (opt->savename_type != -1) {
  906.     char* a=save+strlen(save)-1;
  907.     while(((int) a>(int) save) && (*a!='.') && (*a!='/')) a--;
  908.     if (*a!='.') {   // agh pas de point
  909.       //strcat(save,".none");                 // a Θviter
  910.       strcat(save,".html");                   // prΘfΘrable!
  911.       if ( (opt->debug>1) && (opt->errlog!=NULL) ) {
  912.         fspc(opt->errlog,"warning"); fprintf(opt->errlog,"Default HTML type set for %s%s"LF,adr_complete,fil_complete);
  913.         test_flush;
  914.       }
  915.     }
  916.   }
  917.  
  918.   // effacer pass au besoin pour les autentifications
  919.   // (plus la peine : masquΘ au dΘbut)
  920. /*
  921.   {
  922.     char* a=jump_identification(save);
  923.     if (a!=save) {
  924.       char tempo[HTS_URLMAXSIZE*2];
  925.       char *b;
  926.       tempo[0]='\0';
  927.       strcpy(tempo,"[");
  928.       b=strchr(save,':');
  929.       if (!b) b=strchr(save,'@');
  930.       if (b)
  931.         strncat(tempo,save,(int) b-(int) a);
  932.       strcat(tempo,"]");
  933.       strcat(tempo,a);
  934.       strcpy(save,a);
  935.     }
  936.   }
  937. */
  938.  
  939.   // Θviter les / au dΘbut (cause: N100)
  940.   if (save[0]=='/') {
  941.     char tempo[HTS_URLMAXSIZE*2];
  942.     strcpy(tempo,save+1);
  943.     strcpy(save,tempo);
  944.   }
  945.  
  946.   // changer les ~,:,",*,? en _ pour sauver sur disque
  947.   hts_replace(save,'~','_');  // interdit sous unix (~foo)
  948.   //
  949.   hts_replace(save,'\\','_');
  950.   hts_replace(save,':','_');  // interdit sous windows
  951.   hts_replace(save,'*','_');  // interdit sous windows
  952.   hts_replace(save,'?','_');  // doit pas arriver!!
  953.   hts_replace(save,'\"','_');  // interdit sous windows
  954.   hts_replace(save,'<','_');  // interdit sous windows
  955.   hts_replace(save,'>','_');  // interdit sous windows
  956.   hts_replace(save,'|','_');  // interdit sous windows
  957.   //
  958.   hts_replace(save,'@','_');
  959.   //
  960.   { // Θliminer les // (comme ftp://)
  961.     char* a;
  962.     while( (a=strstr(save,"//")) ) *a='_';
  963.   }
  964.  
  965.    
  966. #if HTS_OVERRIDE_DOS_FOLDERS
  967.   /* Replace /foo/nul/bar by /foo/nul-/bar */
  968.   {
  969.     int i=0;
  970.     while(hts_tbdev[i][0]) {
  971.       char* a=save;
  972.       while((a=strstr(a,hts_tbdev[i]))) {
  973.         switch ( (int) a[strlen(hts_tbdev[i])] ) {
  974.         case '\0':
  975.         case '/':  {
  976.           char tempo[HTS_URLMAXSIZE*2]; tempo[0]='\0';
  977.           strncat(tempo,save,(int) a - (int) save + strlen(hts_tbdev[i]));
  978.           strcat(tempo,"-");
  979.           strcat(tempo,a+strlen(hts_tbdev[i]));
  980.           strcpy(save,tempo);
  981.                    }
  982.           break;
  983.         }
  984.         a+=strlen(hts_tbdev[i]);
  985.       }
  986.       i++;
  987.     }
  988.   }
  989. #endif
  990.  
  991.   // conversion 8-3 .. y compris pour les rΘpertoires
  992.   if (opt->savename_83) {
  993.     char n83[HTS_URLMAXSIZE*2];
  994.     long_to_83(n83,save);
  995.     strcpy(save,n83);
  996.   }
  997.  
  998.  
  999.   /* ensure that there is no ../ (potential vulnerability) */
  1000.   fil_simplifie(save);
  1001.  
  1002.   // chemin primaire Θventuel A METTRE AVANT
  1003.   if (strnotempty(opt->path_html)) {
  1004.     char tempo[HTS_URLMAXSIZE*2];
  1005.     strcpy(tempo,opt->path_html);
  1006.     strcat(tempo,save);
  1007.     strcpy(save,tempo);
  1008.   }
  1009.  
  1010.  
  1011.   // vΘrifier que le nom n'est pas dΘja pris...
  1012.   if (liens!=NULL) { 
  1013.     int nom_ok;
  1014.     do {
  1015.       register int i;
  1016.       register int len;
  1017.       len=strlen(save);    // taille
  1018.       //
  1019.       nom_ok=1;  // α priori bon
  1020.       // on part de la fin pour optimiser, plus les opti de taille pour aller encore plus vite..
  1021. #if DEBUG_SAVENAME
  1022. printf("\nStart search\n");
  1023. #endif
  1024.  
  1025. #if HTS_HASH
  1026.       i=hash_read(hash,save,"",0);      // lecture type 0 (sav)
  1027.       if (i>=0)
  1028. #else
  1029.       for(i=lien_tot-1;i>=0;i--) {
  1030. #if DEBUG_SAVENAME
  1031. printf("%cParse: %d",13,i);
  1032. #endif
  1033.         
  1034.         if (liens[i]->sav_len==len) {    // mΩme taille de chaεne          
  1035. #if HTS_CASSE
  1036.           if (strcmp(liens[i]->sav,save)==0)    // existe dΘja
  1037. #else
  1038.           if (strfield2(liens[i]->sav,save))    // un tel nom existe dΘja
  1039. #endif
  1040. #endif
  1041.           {
  1042. #if HTS_CASSE
  1043.             if ((strcmp(liens[i]->adr,adr)==0) && (strcmp(liens[i]->fil,fil_complete)==0))
  1044. #else
  1045.             if ((strfield2(liens[i]->adr,adr)) && (strfield2(liens[i]->fil,fil_complete)))
  1046. #endif
  1047.             {    // ok c'est le mΩme lien, adresse dΘja dΘfinie
  1048.               //printf("Ok, %s\n",save);
  1049.               //i=lien_tot;    // sortir
  1050.               i=0;
  1051. #if DEBUG_SAVENAME
  1052. printf("\nOK ALREADY DEFINED\n",13,i);
  1053. #endif
  1054.             } else {  // utilisΘ par un AUTRE, changer de nom
  1055.               char tempo[HTS_URLMAXSIZE*2];
  1056.               char* a=save+strlen(save)-1;
  1057.               char* b;
  1058.               int n=2;       
  1059.               tempo[0]='\0';
  1060.  
  1061. #if DEBUG_SAVENAME
  1062. printf("\nWRONG CASE UNMATCH : \n%s\n%s, REDEFINE\n",liens[i]->fil,fil_complete);
  1063. #endif
  1064.               nom_ok=0;
  1065.               i=0;
  1066.               
  1067.               while(((int) a>(int) save) && (*a!='.') && (*a!='\\') && (*a!='/')) a--;
  1068.               if (*a=='.')
  1069.                 strncat(tempo,save,(int) a-(int) save);
  1070.               else
  1071.                 strcat(tempo,save);
  1072.               
  1073.               // tester la prΘsence d'un -xx (ex: index-2.html -> index-3.html)
  1074.               b=tempo+strlen(tempo)-1;
  1075.               while (isdigit((unsigned char)*b)) b--;
  1076.               if (*b=='-') {
  1077.                 sscanf(b+1,"%d",&n);
  1078.                 *b='\0';    // couper
  1079.                 n++;  // plus un
  1080.               }
  1081.               
  1082.               // en plus il faut gΘrer le 8-3 .. pas facile le client
  1083.               if (opt->savename_83) {
  1084.                 int max;
  1085.                 char* a=tempo+strlen(tempo)-1;
  1086.                 while(((int) a>(int) tempo) && (*a!='/')) a--;
  1087.                 if (*a=='/') a++;
  1088.                 max=8-1-nombre_digit(n);
  1089.                 if ((int) strlen(a)>max)
  1090.                   *(a+max)='\0';  // couper sinon il n'y aura pas la place!
  1091.               }
  1092.               
  1093.               // ajouter -xx (ex: index.html -> index-2.html)
  1094.               sprintf(tempo+strlen(tempo),"-%d",n);
  1095.               
  1096.               // ajouter extension
  1097.               if (*a=='.')
  1098.                 strcat(tempo,a);
  1099.               
  1100.               strcpy(save,tempo);
  1101.               
  1102.               //printf("switched: %s\n",save);
  1103.               
  1104.             }  // if
  1105. #if HTS_HASH
  1106.           }
  1107. #else
  1108.           }  // if
  1109.         }  // if sav_len
  1110.       }  // for
  1111. #endif
  1112. #if DEBUG_SAVENAME
  1113. printf("\nEnd search, %s\n",fil_complete);
  1114. #endif
  1115.     } while(!nom_ok);
  1116.     
  1117.   }
  1118.   
  1119.   //printf("'%s' %s %s\n",save,adr,fil);
  1120.       
  1121.   return 0;
  1122. }
  1123.  
  1124. /* nom avec md5 urilisΘ partout */
  1125. void standard_name(char* b,char* dot_pos,char* nom_pos,char* fil_complete,int short_ver) {
  1126.   b[0]='\0';
  1127.   /* Nom */
  1128.   if (dot_pos) {
  1129.     if (!short_ver)    // Noms longs
  1130.       strncat(b,nom_pos,(int) dot_pos - (int) nom_pos);
  1131.     else
  1132.       strncat(b,nom_pos,min((int) dot_pos - (int) nom_pos,8));
  1133.   } else {
  1134.     if (!short_ver)    // Noms longs
  1135.       strcat(b,nom_pos);
  1136.     else
  1137.       strncat(b,nom_pos,8);
  1138.   }
  1139.   /* MD5 - 16 bits */
  1140.   strncat(b,url_md5(fil_complete),4);
  1141.   /* Ext */
  1142.   if (dot_pos) {
  1143.     strcat(b,".");
  1144.     if (!short_ver)    // Noms longs
  1145.       strcat(b,dot_pos+1);
  1146.     else
  1147.       strncat(b,dot_pos+1,3);
  1148.   } else {
  1149.     if (!short_ver)    // Noms longs
  1150.       strcat(b,DEFAULT_EXT);    // pas de..
  1151.     else
  1152.       strcat(b,DEFAULT_EXT_SHORT);    // pas de..
  1153.   }
  1154. }
  1155.  
  1156.  
  1157. /* Petit md5 */
  1158. char* url_md5(char* fil_complete) {
  1159.   static char digest[32+2];
  1160.   char* a;
  1161.   digest[0]='\0';
  1162.   a=strchr(fil_complete,'?');
  1163.   if (a) {
  1164.     if (strlen(a)) {
  1165.       char buff[HTS_URLMAXSIZE*2];
  1166.       a++;
  1167.       digest[0]=buff[0]='\0';
  1168.       strcat(buff,a);         /* query string MD5 */
  1169.       domd5mem(buff,strlen(buff),digest,1,0);
  1170.     }
  1171.   }
  1172.   return digest;
  1173. }
  1174.  
  1175. // interne α url_savename: ajoute une chaεne α une autre avec \ -> /
  1176. void url_savename_addstr(char* d,char* s) {
  1177.   int i=strlen(d);
  1178.   while(*s) {
  1179.     if (*s=='\\')  // remplacer \ par des /
  1180.       d[i++]='/';
  1181.     else
  1182.       d[i++]=*s;
  1183.     s++;
  1184.   }
  1185.   d[i]='\0';
  1186. }
  1187.  
  1188. #undef test_flush
  1189.